﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Reflection;

namespace VitCode.Castle.Helper
{
    /// <summary>
    /// 枚举协助类，用于获取和缓存带有DescriptAttribute的枚举，并且
    /// 把它们按照枚举所定义的DescriptAttribute的名称表示出来
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <example>
    /// <code>
    /// using System.ComponentModel;
    /// using NUnit.Framework;
    /// using WellDell;
    /// namespace TestWellDell
    /// {
    ///   public enum IntEnum
    ///   {
    ///        [OrMemo("中文AA")] aa,
    ///        [OrMemo("中文bb")] bb,
    ///        [OrMemo("中文cc")] cc,
    ///    }
    /// public enum ByteChar :byte
    /// {
    ///		[OrMemo("红色")] red,
    ///		[OrMemo("绿色")] green,
    ///		[OrMemo("蓝色")] blue
    ///	}
    ///
    ///	[TestFixture]
    ///	public class TestEnumTypeHelper
    ///	{
    ///		[Test]
    ///		public void GetString()
    ///		{
    ///			string value = EnumTypeHelper.GetEnumDescript(typeof (IntEnum), IntEnum.aa);
    ///			Assert.IsNotNull(value);
    ///			Assert.AreEqual(value, "中文AA");
    ///
    ///			value = EnumTypeHelper.GetEnumDescript(typeof (ByteChar), ByteChar.red);
    ///			Assert.IsNotNull(value);
    ///			Assert.AreEqual(value, "红色");
    ///			}
    ///		}
    ///	}
    /// </code>
    /// </example>
    public sealed class EnumTypeHelper
    {
        private static Hashtable Cache = new Hashtable();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="enumType"></param>
        private static void AddInCache(Type enumType)
        {
            if (Cache.ContainsKey(enumType))
            {
                return;
            }

            StringDictionary valueDescriptCollection = new StringDictionary();

            //获得特性Description的类型信息
            Type typeDescription = typeof (DescriptionAttribute);

            //获得枚举的字段信息（因为枚举的值实际上是一个static的字段的值）
            FieldInfo[] fields = enumType.GetFields();

            string key;
            string value;

            //检索所有字段
            foreach (FieldInfo field in fields)
            {
                //过滤掉一个不是枚举值的，记录的是枚举的源类型
                if (field.FieldType.IsEnum == true)
                {
                    // 通过字段的名字得到枚举的值
                    // 枚举的值如果是long的话，ToChar会有问题，但这个不在本文的讨论范围之内
                    key = Convert.ToString(enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null));

                    //获得这个字段的所有自定义特性，这里只查找Description特性
                    object[] arr = field.GetCustomAttributes(typeDescription, true);
                    if (arr.Length > 0)
                    {
                        //因为Description这个自定义特性是不允许重复的，所以我们只取第一个就可以了！
                        DescriptionAttribute aa = (DescriptionAttribute) arr[0];
                        //获得特性的描述值，也就是‘男’‘女’等中文描述
                        value = aa.Description;
                    }
                    else
                    {
                        //如果没有特性描述
                        value = field.Name;
                    }
                    valueDescriptCollection.Add(key, value);
                }

            }

            Cache[enumType] = valueDescriptCollection;

        }

        /// <summary>
        /// 获取enumType的Descript表达
        /// </summary>
        /// <param name="enumType">枚举的type</param>
        /// <param name="Value">枚举的数值</param>
        /// <returns></returns>
        public static string GetEnumDescript(Type enumType, object Value)
        {
            StringDictionary enuCollection = (StringDictionary) Cache[enumType];
            if (enuCollection == null)
                AddInCache(enumType);
            enuCollection = (StringDictionary) Cache[enumType];
            return enuCollection[Convert.ToString(Value)];
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="enumValue"></param>
        /// <returns></returns>
        public static string GetEnumDescript(Enum enumValue)
        {
            StringDictionary enuCollection = (StringDictionary) Cache[enumValue.GetType()];
            if (enuCollection == null)
                AddInCache(enumValue.GetType());
            enuCollection = (StringDictionary) Cache[enumValue.GetType()];
            return enuCollection[Convert.ToString(enumValue)];
        }

        /// <summary>
        /// 通过字符串获取Enum的表达
        /// </summary>
        /// <param name="enumDescript"></param>
        /// <param name="enumType"></param>
        /// <returns></returns>
        public static object GetEnumValue(string enumDescript, Type enumType)
        {
            StringDictionary enuCollection = (StringDictionary) Cache[enumType];
            if (enuCollection == null)
                AddInCache(enumType);
            enuCollection = (StringDictionary) Cache[enumType];
            IEnumerator tors = enuCollection.Keys.GetEnumerator();
            while (tors.MoveNext())
            {
                string key = Convert.ToString(tors.Current);
                string value = enuCollection[key];
                if (value == enumDescript)
                {
                    return Enum.Parse(enumType, key,true);
                }
            }
            throw new ArgumentOutOfRangeException("enumDescript", enumDescript, "没有找到对应的枚举类型");
        }

        public static string GetWeekDayName(string dateString)
        {
            var reVal = "";
            var obj = Convert.ToDateTime(dateString).DayOfWeek;
            if (obj == DayOfWeek.Monday)
                reVal = "星期一";
            else if (obj == DayOfWeek.Tuesday)
                reVal = "星期二";
            else if (obj == DayOfWeek.Wednesday)
                reVal = "星期三";
            else if (obj == DayOfWeek.Thursday)
                reVal = "星期四";
            else if (obj == DayOfWeek.Friday)
                reVal = "星期五";
            else if (obj == DayOfWeek.Saturday)
                reVal = "星期六";
            else if (obj == DayOfWeek.Sunday)
                reVal = "星期日";
            return reVal;
        }
    }
}
